package com.nut.article.interceptor;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * jwt加解密工具类
 */
@Component
@Slf4j
public class JwtTokenUtil implements Serializable {

    private static final long serialVersionUID = -3301605591108950415L;

//    private static final String KEY_OPEN_ID = "openId";
    private static final String KEY_USER_ID = "userId";
    private static final String KEY_USER_NAME = "username";
    private static final String KEY_CREATED = "created";

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private Long expiration;

    public UserJwt getUserJwtFormToken(String token) {
        try {
            final Claims claims = getClaimsFromToken(token);
            if (claims != null) {
                UserJwt userJwt = new UserJwt();
                if (claims.get(KEY_USER_NAME) != null) {
                    userJwt.setUsername(String.valueOf(claims.get(KEY_USER_NAME)));
                }
                if (claims.get(KEY_USER_ID) != null) {
                    userJwt.setUserId(Integer.valueOf(claims.get(KEY_USER_ID).toString()));
                }
                return userJwt;
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    public Date getCreatedDateFromToken(String token) {
        Date created;
        try {
            final Claims claims = getClaimsFromToken(token);
            created = new Date((Long) claims.get(KEY_CREATED));
        } catch (Exception e) {
            created = null;
        }
        return created;
    }

    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    public Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.error("jwt_error," + e);
            claims = null;
        }
        return claims;
    }

    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
        return (lastPasswordReset != null && created.before(lastPasswordReset));
    }

    public String generateToken(UserJwt userJwt) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(KEY_USER_NAME, userJwt.getUsername());
        claims.put(KEY_USER_ID, userJwt.getUserId());
        return generateToken(claims);
    }

    private String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
        final Date created = getCreatedDateFromToken(token);
        return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
                && !isTokenExpired(token);
    }

    public String refreshToken(String token) {
        String refreshedToken;
        try {
            final Claims claims = getClaimsFromToken(token);
            claims.put(KEY_CREATED, new Date());
            refreshedToken = generateToken(claims);
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }

    public Boolean validateToken(String token, UserJwt userJwt) {
        final UserJwt user = getUserJwtFormToken(token);
        final Date created = getCreatedDateFromToken(token);
        return (
                user.getUserId().equals(userJwt.getUserId())
                        && !isTokenExpired(token));
    }

    public static void main(String[] args) {

        System.out.println(UUID.randomUUID().toString().replace("-", ""));
        System.out.println(UUID.randomUUID().toString().replace("-", ""));
        System.out.println(UUID.randomUUID().toString().replace("-", ""));


        UserJwt userJwt = new UserJwt();
//        userJwt.setCardno("cardno");
//        userJwt.setMobile("mobile");
        userJwt.setUsername("openId");
        userJwt.setUserId(1);

        JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();

        String token = jwtTokenUtil.generateToken(userJwt);




//        String openid = jwtTokenUtil.getOpenidFromToken(token);
//        System.out.println(openid);


    }
}

